function Objective = ecmlsrobj(Data, Design, Param, Covar)
%ECMLSROBJ Objective function for least-squares regression (with missing data).
% Least-squares objective function based on current parameter estimates with
% missing data.
%
%	Objective = ecmlsrobj(Data, Design, Param, Covar);
%
% Inputs:
%	Data - NUMSAMPLES x NUMSERIES matrix with NUMSAMPLES samples of a
%		NUMSERIES-dimensional random vector. Missing values are represented as
%		NaNs. Only samples that are entirely NaNs are ignored (to ignore samples
%		with at least one NaN, use MVNRMLE).
%	Design - Either a matrix or a cell-array to handle two distinct model
%		structures. First, if NUMSERIES = 1, Design can be a NUMSAMPLES x
%		NUMPARAMS matrix with known values. This is the "standard" form for
%		regression on a single data series. Alternatively, for any NUMSERIES
%		>= 1, Design can be a cell array of either 1 or NUMSAMPLES cells, where
%		each cell contains a NUMSERIES x NUMPARAMS matrix of known values. If
%		Design has a single cell, then it is assumed to be the same Design
%		matrix for each sample. Otherwise, Design must contain individual Design
%		matrices for each sample.
%	Param - NUMPARAMS x 1 column vector of estimates for the parameters of the
%		regression model.
%
% Optional Inputs:
%	Covar - NUMSERIES x NUMSERIES matrix of user-supplied estimates for the
%		covariance of the residuals of the regression, i.e., weighted
%		least-squares.
%
% Outputs:
%	Objective - A scalar that contains the least-squares objective function.
%
% Notes:
%	This function requires Covar to be positive-definite.
%
%	Note that
%		ecmlsrobj(Data, Design, Param)
%			= ecmmvnrrobj(Data, Design, Param, IdentityMatrix)
%	where IdentityMatrix is a NumSeries x NumSeries identity matrix.
%
% See also ECMLSRMLE, MVNRMLE, MVNROBJ.

%	Copyright 2005 The MathWorks, Inc.
%	$Revision: 1.1.6.2 $ $Date: 2005/12/12 23:16:06 $

if nargin < 4
	Covar = [];
end

if nargin < 3
	error('Finance:ecmlsrobj:MissingInputArg', ...
		'Missing required arguments Data, Design, or Param.');
end

if isempty(Data)
	error('Finance:ecmlsrobj:EmptyDataArray', ...
		'Empty required input argument Data.');
end
if isempty(Design)
	error('Finance:ecmlsrobj:EmptyDesignArray', ...
		'Empty required input argument Design.');
end
if isempty(Param)
	error('Finance:ecmlsrobj:EmptyParam', ...
		'Empty required input argument Param.');
end

Param = Param(:);

%[NumSamples, NumSeries, NumParams] = ...
%	checkecmmvnrsetup(Data, Design, Param, Covar);

[NumSamples, NumSeries] = size(Data);
NumParams = size(Param,1);

if iscell(Design) && (numel(Design) == 1)
	SingleDesign = true;
else
	SingleDesign = false;
end

if isempty(Covar)
	Covar = eye(NumSeries, NumSeries);
end

[CholCovar, CholState] = chol(Covar);
if CholState > 0
	warning('Finance:ecmlsrobj:NonPosDefCov', ...
		'Covariance matrix is not positive-definite. Will use an identity matrix.');
	Covar = eye(NumSeries, NumSeries);
	CholCovar = eye(NumSeries, NumSeries);
end

LogTwoPi = log(2.0 * pi);
LogDetCovar = 2.0 * sum(log(diag(CholCovar)));

Count = 0;
Objective = 0.0;

for k = 1:NumSamples
	
	P = ~isnan(Data(k,:));
	Available = sum(P);
	
	if Available > 0
		Count = Count + 1;

		Objective = Objective - 0.5 * Available * LogTwoPi;

		if iscell(Design)
			if SingleDesign
				Mean = Design{1} * Param;
			else
				Mean = Design{k} * Param;
			end
		else
			Mean = Design(k,:) * Param;
		end

        if Available < NumSeries
			[SubChol, CholState] = chol(Covar(P,P));
			
			if CholState > 0
				error('Finance:ecmlsrobj:NonPosDefSubCov', ...
					'Sub-covariance not positive-definite.');
			end
			
			SubResid = SubChol' \ (Data(k,P)' - Mean(P));

			Objective = Objective - 0.5 * SubResid' * SubResid;
			Objective = Objective - sum(log(diag(SubChol)));
		else
			Resid = CholCovar' \ (Data(k,:)' - Mean);

			Objective = Objective - 0.5 * Resid' * Resid;
			Objective = Objective - 0.5 * LogDetCovar;
		end
	end
end
